package com.company.biz.user.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.company.biz.user.mapper.UserDao;
import com.company.biz.user.service.DepartmentService;
import com.company.biz.user.service.PositionService;
import com.company.biz.user.service.UserLogService;
import com.company.biz.user.service.UserService;
import com.company.common.enums.ExecuteErrorEnum;
import com.company.common.enums.TableNamePrefixEnum;
import com.company.common.enums.UserErrorEnum;
import com.company.common.exception.BizException;
import com.company.common.util.*;
import com.company.user.entity.DepartmentEntity;
import com.company.user.entity.PositionEntity;
import com.company.user.entity.UserEntity;
import com.company.user.req.*;
import com.company.user.resp.ImportAddStaffListResp;
import com.company.user.resp.UserInfoResp;
import com.company.user.vo.ExcelStaffListVo;
import com.company.user.vo.StaffListStateVO;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.io.File;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
public class UserServiceImpl extends ServiceImpl<UserDao, UserEntity> implements UserService {

    @Resource
    private UserDao userDao;

    @Resource
    private UserLogService userLogService;

    @Resource
    private UserService userService;

    @Resource
    private DepartmentService departmentService;

    @Resource
    private PositionService positionService;

    /**
     * 用户的分页查询
     */
    @Override
    public Page<UserInfoResp> getUserListPage(UserListPageReq req, UserEntity user) {
        LambdaQueryWrapper<UserEntity> lambda = new QueryWrapper<UserEntity>().lambda();

        //用户名 精准查询
        lambda.eq(StringUtils.isNotEmpty(req.getLoginName()), UserEntity::getLoginName, req.getLoginName());

        //用户真实性名 查询
        lambda.like(StringUtils.isNotEmpty(req.getUserName()), UserEntity::getUserName, req.getUserName());

        //部门id 筛选
        lambda.eq(StringUtils.isNotEmpty(req.getDepartmentId()), UserEntity::getDepartmentId, req.getDepartmentId());

        //职务id 筛选
        lambda.eq(StringUtils.isNotEmpty(req.getPositionId()), UserEntity::getPositionId, req.getPositionId());

        //是否被删除
        lambda.eq(UserEntity::getIsDel,"n");

        if ("ASC".equals(req.getUserSort())) {
            lambda.orderByAsc(UserEntity::getCreateTime);
        }
        if ("DESC".equals(req.getUserSort())) {
            lambda.orderByDesc(UserEntity::getCreateTime);
        }
        Page<UserEntity> userEntityPage = userDao.selectPage(new Page<>(req.getPage(), req.getSize()), lambda);

        //补充数据
        List<UserInfoResp> userInfoRespList = new ArrayList<>();
        List<UserEntity> records = userEntityPage.getRecords();
        for (UserEntity record : records) {
            UserInfoResp userInfoResp = new UserInfoResp();
            record.copyTo(userInfoResp);
            userInfoRespList.add(userInfoResp);
        }
        //补充部门名
        supplementDepartmentName(userInfoRespList);
        //补充职位名
        supplementPositionName(userInfoRespList);
        Page<UserInfoResp> userInfoRespPage = new Page<>();
        userInfoRespPage.setCountId(userEntityPage.getCountId());
        userInfoRespPage.setSize(userEntityPage.getSize());
        userInfoRespPage.setTotal(userEntityPage.getTotal());
        userInfoRespPage.setRecords(userInfoRespList);
        return userInfoRespPage;
    }

    /**
     * 通过登入名 电话号码 邮箱 获取用户
     *
     * @return
     */
    @Override
    public UserEntity getUserByLoginNameOrPhoneOrEmail(String loginNameOrPhoneOrEmail) {
        LambdaQueryWrapper<UserEntity> lambdaQueryWrapper = new QueryWrapper<UserEntity>().lambda()
                .eq(UserEntity::getLoginName, loginNameOrPhoneOrEmail)
                .or().eq(UserEntity::getEmail, loginNameOrPhoneOrEmail)
                .or().eq(UserEntity::getPhoneNumber, loginNameOrPhoneOrEmail);
        return userDao.selectOne(lambdaQueryWrapper);
    }

    //密码必须由字母 数字 特殊符号组成 且要大于8位
    public static final String PW_PATTERN = "^(?![A-Za-z0-9]+$)(?![A-Za-z\\W]+$)[a-zA-Z0-9\\W]{8,12}$";

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean addUser(AddUserReq req, UserEntity user) {
        //校验密码是否合格
        if (!req.getPassword().matches(PW_PATTERN)) {
            throw new BizException(ExecuteErrorEnum.EXECUTE_PASSWORDERROR_ENUM);
        }
        //校验用户名是否重复
        UserEntity userEntity1 = userDao.selectOne(new QueryWrapper<UserEntity>().lambda()
                .eq(StringUtils.isNotBlank(req.getLoginName()), UserEntity::getLoginName, req.getLoginName())
        );
        if (userEntity1 != null) {
            throw new BizException(UserErrorEnum.USERNAME_EXISTS);
        }
        UserEntity userEntity = new UserEntity();
        req.copyTo(userEntity);
        Date date = new Date();
        userEntity.setPassword(BCryptUtil.hashpw(req.getPassword()));
        userEntity.setUserId(IdentifierGeneratorUtil.getOwnId(TableNamePrefixEnum.TBUSER));
        userEntity.setCreateTime(date);
        userEntity.setUpdateTime(date);
        userLogService.addUserLog(userEntity.getUserId(), req.getIp(), "添加用户", user.getUserName() + "添加用户" + userEntity.getLoginName());
        return this.save(userEntity);
    }

    @Override
    public ImportAddStaffListResp importAddStaffList(MultipartFile file) {
        //excel表格数据处理
        List<ExcelStaffListVo> excelStaffListVos = ImportExcelUtils.importStaffUser(file);
        excelStaffListVos.forEach(System.out::println);
        //插入成功的
        List<StaffListStateVO> successStaffListVO = new ArrayList<>();
        List<UserEntity> userEntities = new ArrayList<>();
        //插入失败的
        List<StaffListStateVO> failStaffListVO = new ArrayList<>();
        //excel重复数据判断(账号 、 电话号码 )
        //账号判断
        Map<String, List<ExcelStaffListVo>> loginName_staff_map = excelStaffListVos.stream().filter(excelStaffListVo -> StringUtils.isNotBlank(excelStaffListVo.getLoginName())).collect(Collectors.groupingBy(ExcelStaffListVo::getLoginName));
        loginName_staff_map.forEach((key, value) -> {
            if (value.size() >= 2) {
                excelStaffListVos.removeAll(value);
                List<Integer> rowList = value.stream().map(ExcelStaffListVo::getRow).collect(Collectors.toList());
                String rowString = "";
                for (Integer integer : rowList) {
                    rowString = rowString + "第" + integer + "行";
                }
                for (ExcelStaffListVo excelStaffListVo : value) {
                    StaffListStateVO staffListStateVO = new StaffListStateVO();
                    staffListStateVO.setRow(excelStaffListVo.getRow());
                    staffListStateVO.setStaffName(excelStaffListVo.getUserName());
                    staffListStateVO.setReason("第" + excelStaffListVo.getRow() + "的数据与" + rowString + ",员工" + excelStaffListVo.getLoginName() + "的账号重复了");
                    failStaffListVO.add(staffListStateVO);
                }
            }
        });
        //账号判断
        Map<String, List<ExcelStaffListVo>> phoneNumber_staff_map = excelStaffListVos.stream().filter(excelStaffListVo -> StringUtils.isNotBlank(excelStaffListVo.getPhoneNumber())).collect(Collectors.groupingBy(ExcelStaffListVo::getPhoneNumber));
        phoneNumber_staff_map.forEach((key, value) -> {
            if (value.size() >= 2) {
                excelStaffListVos.removeAll(value);
                List<Integer> rowList = value.stream().map(ExcelStaffListVo::getRow).collect(Collectors.toList());
                String rowString = "";
                for (Integer integer : rowList) {
                    rowString = rowString + "第" + integer + "行";
                }
                for (ExcelStaffListVo excelStaffListVo : value) {
                    StaffListStateVO staffListStateVO = new StaffListStateVO();
                    staffListStateVO.setRow(excelStaffListVo.getRow());
                    staffListStateVO.setStaffName(excelStaffListVo.getUserName());
                    staffListStateVO.setReason("第" + excelStaffListVo.getRow() + "的数据与" + rowString + ",员工" + excelStaffListVo.getPhoneNumber() + "的电话号码重复了");
                    failStaffListVO.add(staffListStateVO);
                }
            }
        });


        for (int i = 0; i < excelStaffListVos.size(); i++) {
            ExcelStaffListVo excelStaffListVo = excelStaffListVos.get(i);
            //初始化该条数据是否导入成功
            StaffListStateVO staffListStateVO = new StaffListStateVO();
            //excel员工姓名判断
            if (StringUtils.isBlank(excelStaffListVo.getUserName())) {
                staffListStateVO.setRow(excelStaffListVo.getRow());
                staffListStateVO.setStaffName(excelStaffListVo.getUserName());
                staffListStateVO.setReason("第" + excelStaffListVo.getRow() + "的数据,员工的姓名为空");
                failStaffListVO.add(staffListStateVO);
                continue;
            }
            //excel员工账号判断
            if (StringUtils.isBlank(excelStaffListVo.getLoginName())) {
                staffListStateVO.setRow(excelStaffListVo.getRow());
                staffListStateVO.setStaffName(excelStaffListVo.getUserName());
                staffListStateVO.setReason("第" + excelStaffListVo.getRow() + "的数据,账号为空");
                failStaffListVO.add(staffListStateVO);
                continue;
            }
            //excel员工部门判断
            if (StringUtils.isBlank(excelStaffListVo.getDepartmentId())) {
                staffListStateVO.setRow(excelStaffListVo.getRow());
                staffListStateVO.setStaffName(excelStaffListVo.getUserName());
                staffListStateVO.setReason("第" + excelStaffListVo.getRow() + "的数据,部门为空");
                failStaffListVO.add(staffListStateVO);
                continue;
            }
            //excel员工职位判断
            if (StringUtils.isBlank(excelStaffListVo.getPositionId())) {
                staffListStateVO.setRow(excelStaffListVo.getRow());
                staffListStateVO.setStaffName(excelStaffListVo.getUserName());
                staffListStateVO.setReason("第" + excelStaffListVo.getRow() + "的数据,职位为空");
                failStaffListVO.add(staffListStateVO);
                continue;
            }
            //数据库验证账号
            if (ObjectUtil.isNotEmpty(userDao.selectOne(new QueryWrapper<UserEntity>().lambda().eq(UserEntity::getLoginName, excelStaffListVo.getLoginName())))) {
                staffListStateVO.setRow(excelStaffListVo.getRow());
                staffListStateVO.setStaffName(excelStaffListVo.getUserName());
                staffListStateVO.setReason("第" + excelStaffListVo.getRow() + "的数据,该账号" + excelStaffListVo.getLoginName() + "已注册");
                failStaffListVO.add(staffListStateVO);
                continue;
            }
            //数据库验证手机号
            if (StringUtils.isNotBlank(excelStaffListVo.getPhoneNumber())) {
                if (ObjectUtil.isNotEmpty(userDao.selectOne(new QueryWrapper<UserEntity>().lambda().eq(UserEntity::getPhoneNumber, excelStaffListVo.getPhoneNumber())))) {
                    staffListStateVO.setRow(excelStaffListVo.getRow());
                    staffListStateVO.setStaffName(excelStaffListVo.getUserName());
                    staffListStateVO.setReason("第" + excelStaffListVo.getRow() + "的数据,该电话号码" + excelStaffListVo.getPhoneNumber() + "已注册");
                    failStaffListVO.add(staffListStateVO);
                    continue;
                }
            }
            UserEntity userEntity = new UserEntity();
            userEntity.setUserId(IdentifierGeneratorUtil.getOwnId(TableNamePrefixEnum.TBUSER));
            userEntity.setCreateTime(new Date());
            userEntity.setUpdateTime(new Date());
            userEntity.setIsDel("n");
            excelStaffListVo.copyTo(userEntity);
            staffListStateVO.setRow(excelStaffListVo.getRow());
            staffListStateVO.setStaffName(excelStaffListVo.getUserName());
            staffListStateVO.setReason("员工:" + excelStaffListVo.getUserName() + "导入成功");
            successStaffListVO.add(staffListStateVO);
            userEntities.add(userEntity);
        }
        if (CollUtil.isNotEmpty(userEntities)) {
            userService.saveBatch(userEntities);
        }
        //添加数据
        ImportAddStaffListResp importAddStaffListResp = new ImportAddStaffListResp();
        importAddStaffListResp.setSuccessStaffListVO(successStaffListVO);
        importAddStaffListResp.setFailStaffListVO(failStaffListVO);
        return importAddStaffListResp;
    }

    @Override
    public UserInfoResp getUserInfoByUserId(GetUserInfoByUserIdReq req, UserEntity user) {
        LambdaQueryWrapper<UserEntity> userEntityLambdaQueryWrapper = new QueryWrapper<UserEntity>()
                .lambda().eq(StringUtils.isNotEmpty(req.getUserId()), UserEntity::getUserId, req.getUserId());
        UserEntity userEntity = userDao.selectOne(userEntityLambdaQueryWrapper);
        UserInfoResp userInfoResp = new UserInfoResp();
        userEntity.copyTo(userInfoResp);
        if(StringUtils.isNotBlank(userInfoResp.getPositionId())){
            PositionEntity positionEntity = positionService.getById(userInfoResp.getPositionId());
            if(ObjectUtil.isNotEmpty(positionEntity)){
                userInfoResp.setPositionName(positionEntity.getPositionName());
            }
        }
        if(StringUtils.isNotBlank(userInfoResp.getDepartmentId())){
            DepartmentEntity departmentEntity = departmentService.getById(userInfoResp.getDepartmentId());
            if(ObjectUtil.isNotEmpty(departmentEntity)){
                userInfoResp.setDepartmentName(departmentEntity.getDepartmentName());
            }
        }
        return userInfoResp;
    }

    @Override
    public boolean updateUserInfoByUserInfo(UpdateUserInfoByUserInfoReq req, UserEntity user) {
        UserEntity userEntity = new UserEntity();
        req.copyTo(userEntity);
        userEntity.setUpdateTime(new Date());
        userEntity.setPassword(BCryptUtil.hashpw(req.getPassword()));
        return saveOrUpdate(userEntity, new UpdateWrapper<UserEntity>().lambda().eq(UserEntity::getUserId, req.getUserId()));
    }

    @Override
    public boolean deleteUserInfoByUserIds(DeleteUserInfoByUserIdsReq req, UserEntity user) {
        LambdaUpdateWrapper<UserEntity> lambda = new UpdateWrapper<UserEntity>().lambda();
        lambda.set(UserEntity::getUserStatus, "1");
        lambda.in(UserEntity::getUserId, req.getUserIds());
        return update(lambda);
    }

    @Override
    public boolean resetPassword(String userId) {
        LambdaUpdateWrapper<UserEntity> userEntityLambdaUpdateWrapper = new UpdateWrapper<UserEntity>().lambda().eq(UserEntity::getUserId, userId)
                .set(UserEntity::getPassword, BCryptUtil.hashpw("888888"));
        return update(userEntityLambdaUpdateWrapper);
    }

    //用户补充部门名
    public void supplementDepartmentName(List<UserInfoResp> userInfoRespList){
        //补充部门名
        DirectFieldFiller<String, DepartmentEntity, UserInfoResp> DepartmentNameFiller = new DirectFieldFiller<String, DepartmentEntity, UserInfoResp>() {
            @Override
            public String whichIdNeed(UserInfoResp obj) {
                return obj.getDepartmentId();
            }

            @Override
            public String getIdFromValue(DepartmentEntity obj) {
                return obj.getDepartmentId();
            }

            @Override
            public List<DepartmentEntity> loadFromDB(List<String> ids) {
                return departmentService.list(new QueryWrapper<DepartmentEntity>().lambda().in(DepartmentEntity::getDepartmentId,ids));
            }

            @Override
            public void fillField(UserInfoResp obj, DepartmentEntity val) {
                obj.setDepartmentName(val.getDepartmentName());
            }
        };
        DepartmentNameFiller.fill(userInfoRespList);
    }
    //用户补充职位名
    public void supplementPositionName(List<UserInfoResp> userInfoRespList){
        //补充部门名
        DirectFieldFiller<String, PositionEntity, UserInfoResp> PositionNameFiller = new DirectFieldFiller<String, PositionEntity, UserInfoResp>() {
            @Override
            public String whichIdNeed(UserInfoResp obj) {
                return obj.getPositionId();
            }

            @Override
            public String getIdFromValue(PositionEntity obj) {
                return obj.getPositionId();
            }

            @Override
            public List<PositionEntity> loadFromDB(List<String> ids) {
                return positionService.list(new QueryWrapper<PositionEntity>().lambda().in(PositionEntity::getPositionId,ids));
            }

            @Override
            public void fillField(UserInfoResp obj, PositionEntity val) {
                obj.setPositionName(val.getPositionName());
            }
        };
        PositionNameFiller.fill(userInfoRespList);
    }

}
